#include <iostream>
#include "../why/utility/Singleton.hpp"
#include "../why/win/UnhandledException.h"
#include "../why/synchronization/Lock.h"
#include "../why/utility/MyBind.hpp"
#include "../why/threading/Thread.h"
#include "vld.h"

using namespace std;
using namespace why::win;
using namespace why::utility;
using namespace why::synchronization;
using namespace why::threading;

class A: public Singleton<A>
{
protected:
    A(int a = 10, int b = 10): a_(a), b_(b){};
    ~A(){}

public:
    int GetA(){return a_+ 100;}
    int GetB(){return b_ + 100;}
    void SetA(int a){a_ = a;}
    void SetB(int b){b_ = b;}

private:
    int a_;
    int b_;
    DISALLOW_COPY_AND_ASSIGN(A);
    friend class Singleton<A>;
};

class B
{
protected:
    B(int a = 10, int b = 10): a_(a), b_(b)
    {
        typedef Singleton<A> origin;
        cout << origin::GetInstance()->GetA() << endl;
        cout << origin::GetInstance()->GetB() << endl;
    }
    ~B(){}

public:
    int GetA(){return a_ + 1000;}
    int GetB(){return b_ + 1000;}
    void SetA(int a){a_ = a;}
    void SetB(int b){b_ = b;}

private:
    int a_;
    int b_;
    DISALLOW_COPY_AND_ASSIGN(B);
    friend class Singleton<B>;
};

//A::A(int a, int b): a_(a), b_(b)
//{
//    typedef Singleton<B> origin;
//    cout << origin::GetInstance()->GetA() << endl;
//    cout << origin::GetInstance()->GetB() << endl;
//}

void tow_arguments(int i)
{
    cout << i << endl;
    Sleep(10000);
}

void tow_arguments(int i, int j)
{
    cout << i << "  " << j << "  " << endl;
}

void tow_arguments(int i, int j, int z)
{
    cout << i << "  " << j << "  " << z << "  " << endl;
}

class Test 
{
    public:
        void test(int i, int j, int z)
        {
            cout << "This is a menber func!" << endl;
            cout << i << "  " << j << "  " << z << endl;
        }
        void test(int i)
        {
            cout << "This is a menber func!" << endl;
            cout << i << endl;
        }
        void test(int i, int j)
        {
            cout << "This is a menber func!" << endl;
            cout << i << "  " << j << "  " << endl;
        }
        void test(int i, int j, int z, int m)
        {
            cout << "This is a menber func!" << endl;
            cout << i << "  " << j << "  " << z << "  " << m << endl;
        }
        void test(int i, int j, int z, int m, int n)
        {
            cout << "This is a menber func!" << endl;
            cout << i << "  " << j << "  " << z << "  " << m << "  " << n << endl;
        }
};

void testclass(Test *t)
{
    cout << "testclass,Test,int" << endl;
}

int main(void)
{
    std::locale::global(std::locale(""));

    //typedef Singleton<A> origin;
    //cout << origin::GetInstance()->GetA() << endl;

    //int i = 1, j = 2;
    //boost::bind2(&tow_arguments, _1, _2)(i, j);
    //boost::bind(&tow_arguments, 1, 1)(j, j);
    //boost::bind(tow_arguments, j)(i);
    //Function1<void, int> *fun = why::utility::Bind(tow_arguments, j);
    //(*fun)(i);

    Test t;
    //why::utility::Bind(testclass, &t)();
    //why::utility::Bind(&Test::test, &t, 3, 2, 5)();
    //why::utility::Bind(&Test::test, &t, 3, 2)();
    //why::utility::Bind(&Test::test, &t, 3, 2, 5 ,6)();
    //why::utility::Bind(&Test::test, &t, 3, 2, 5, 6, 7)();
    //why::utility::Bind(&Test::test, &t, 3)();
    
    //boost::bind(&Test::test, &t);
    //boost::bind2(&testclass, _1, 666)(t, j);
    //boost::bind2(&testclass, t, j)(i, j);

 /*   const Function &fun = why::utility::Bind(tow_arguments, i, j, i);*/

    //fun();

    //Thread *thread = new Thread(testclass, &t);
    Thread thread(tow_arguments, 0);
    if (thread.ThreadWasStarted())
    {
        cout << "true" << endl;
    }
    else 
    {
        cout << "false" << endl;
    }
    thread.Join();

    if (!thread.ThreadWasStarted())
    {
        cout << "false" << endl;
    }
    else 
    {
        cout << "true" << endl;
    }

    getchar();

    return 0;
}

